package br.ita.battlefarm.players;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import br.ita.battlefarm.core.Board;
import br.ita.battlefarm.core.Game;
import br.ita.battlefarm.core.InitialConditions;
import br.ita.battlefarm.core.Position;
import br.ita.battlefarm.moves.Move;
import br.ita.battlefarm.pieces.Piece;

import android.content.Context;
import android.view.View;

public class AIPlayer extends Player {
	
	public List<Move> _moves;
	private int _difficulty = 1;
	
	public AIPlayer(InitialConditions initialConditions) {
		super(initialConditions);
		ArrayList<Piece> pieceList = new ArrayList<Piece>();
		for( Class classe : initialConditions.getPiecesSet() ){
			try {
				pieceList.add((Piece)classe.newInstance());
			} catch (IllegalAccessException e) {
				
			} catch (InstantiationException e) {
				
			}
		}
		getBoard().randomInsertPieceList(pieceList);
		_moves = Game.getInstance().generateAndRetrieveMoves();
	}

	@Override
	public Position getNextMovePosition(){	
		if(_difficulty == 0){
			return getNextMovePositionEasy();
		}
		else{
			return getNextMovePositionMedium();
		}
	}
	
	private Position getNextMovePositionEasy(){
		Board enemyBoard = Game.getInstance().getEnemyBoardAgainstPlayer(this);
		Random random = new Random();
		
		//Right now we have access to all the enemy board. There should be a way to get a "masked board".
		while(true){
			int i = random.nextInt(enemyBoard.getNumRows());
			int j = random.nextInt(enemyBoard.getNumColumns());
			if( enemyBoard.validPlayPosition(i, j) ){
				return new Position(i,j);
			}
		}
	}
	
	private Position getNextMovePositionMedium(){
		Board enemyBoard = Game.getInstance().getEnemyBoardAgainstPlayer(this);
		Random random = new Random();
		
		List<Position> candidatePositionsForShootingAround = new ArrayList<Position>();
		
		for(Position position : enemyBoard.getPieceHitPositions()){
			if(!enemyBoard.getPieceThatOccupiesPosition(position).isDead()){
				int x = position.x;
				int y = position.y;
				checkAndAddCoordinates(enemyBoard, candidatePositionsForShootingAround, x-1, y-1);
				checkAndAddCoordinates(enemyBoard, candidatePositionsForShootingAround, x, y-1);
				checkAndAddCoordinates(enemyBoard, candidatePositionsForShootingAround, x+1, y-1);
				checkAndAddCoordinates(enemyBoard, candidatePositionsForShootingAround, x-1, y);
				checkAndAddCoordinates(enemyBoard, candidatePositionsForShootingAround, x+1, y);
				checkAndAddCoordinates(enemyBoard, candidatePositionsForShootingAround, x-1, y+1);
				checkAndAddCoordinates(enemyBoard, candidatePositionsForShootingAround, x, y+1);
				checkAndAddCoordinates(enemyBoard, candidatePositionsForShootingAround, x+1, y+1);
			}
		}
		
		if(candidatePositionsForShootingAround.size() == 0){
			return getNextMovePositionEasy();
		}
		else{
			//AI IS SMARTER IF WE DO NOT FILTER DUPLICATES (Higher probability for more surrounded positions) 
			
			int index = random.nextInt(candidatePositionsForShootingAround.size());
			return candidatePositionsForShootingAround.get(index);
		}
	}

	private void checkAndAddCoordinates(Board enemyBoard, List<Position> candidatePositionsForShootingAround, int x, int y) {
		if(enemyBoard.validPlayPosition(x, y)){
			candidatePositionsForShootingAround.add(new Position(x, y));
		}
	}
	
	@Override
	public View createView(Context activity) {
		return super.createView(activity);
	}
	
	public View getView(){
		return super.getBoard().getView();
	}

	@Override
	public void cellPress(int i, int j, Move move) {
		//Movimento do computador
		Player enemy = Game.getInstance().getEnemyPlayer(this);
		//Select enemy move
		if(move == null){
			move = getNextMoveChoice();
		}
		
		move.fire(enemy.getBoard(), i, j);
		Game.getInstance().changeToNextState();
	}

	private Move getNextMoveChoice() {
		List<Move> moves = getAvailableMoveChoices();
		Random random = new Random();
		int index = random.nextInt(moves.size());
		return moves.get(index);
	}
	
	private List<Move> getAvailableMoveChoices(){
		List<Move> moves = new ArrayList<Move>();
		for(Move move : _moves){
			if(move.hasMovesLeft()){
				moves.add(move);
			}
		}
		return moves;
	}

	@Override
	public void cellPressDuringSetup(int i, int j) {
		//do nothing (AI never presses anything during setup
	}
	
}
